﻿Imports System.IO.Ports
Imports System.Text
Imports System.Threading
Imports FL_8x0.FL_800.Model
Imports GalaSoft.MvvmLight.Messaging

Namespace FL_8x0.Common

    Public Class SerialPortServerSync

        Private _mode As String
        Private _version As String

        Private _serialPort As New SerialPort
        Private _strBuffer As String = ""
        Private _strOperateCommand As String

        Private _groupModel As New GroupModel
        Private _resultModel As New ResultModel

        Private _isWritten As Boolean

        Private _cmdQueue As Queue(Of Cmd)

        Private _isRunning As Boolean

        Private _info As New MiddleInfoModel

        Private _timeOut As UShort = 10000

        Public Const ENQ = 5
        Public Const ACK = 6
        Public Const NAK = 15

        Public Const STX = 2
        Public Const ETX = 3

        Public Property IsRunning() As Boolean
            Get
                Return _isRunning
            End Get
            Set(ByVal value As Boolean)
                _isRunning = value
            End Set
        End Property

        Public Property GroupMode As GroupModel
            Get
                Return _groupModel
            End Get
            Set(value As GroupModel)
                _groupModel = value
            End Set
        End Property

        Public Property IsWritten As Boolean
            Get
                Return Volatile.Read(_isWritten)
            End Get
            Set(value As Boolean)
                Volatile.Write(_isWritten, value)
            End Set
        End Property

        Public Function StartServer(ByVal strMode As String) As Boolean
            If _serialPort.IsOpen Then
                _serialPort.Close()
                RemoveHandler _serialPort.DataReceived, AddressOf DataReceived
            End If
            Dim modes As String() = strMode.Split(",")
            _mode = modes(2)
            _version = modes(3)
            _groupModel.IsMs = _mode.Contains("MS")

            _serialPort.PortName = modes(0)
            _serialPort.BaudRate = Integer.Parse(modes(1))
            _serialPort.DataBits = 8
            _serialPort.StopBits = 1
            _serialPort.Parity = Parity.None
            _serialPort.Handshake = Handshake.None
            AddHandler _serialPort.DataReceived, AddressOf DataReceived
            _cmdQueue = New Queue(Of Cmd)
            Try
                _serialPort.Open()
            Catch ex As Exception
                MsgBox(ex.Message)
                Return False
            End Try
            _isRunning = True
            Return True
        End Function

        '======================================================================================
        '模 块 名：CutBuffer
        '入    口：intLength = 指定个数
        '出    口：指定个数的字符
        '引用模块：strUartBuffer
        '功    能：从缓冲区截取指定个数的字符
        '======================================================================================
        Private Function CutBuffer(ByVal intLength As Integer) As String
            If intLength < Len(_strBuffer) Then
                CutBuffer = Mid(_strBuffer, 1, intLength)
                _strBuffer = Mid(_strBuffer, 1 + intLength)
            Else
                CutBuffer = _strBuffer
                _strBuffer = ""
            End If

        End Function

        Private Sub ClearBuffer()
            _strBuffer = ""
        End Sub

        Public Function StopServer()
            _strBuffer = ""
            If _serialPort.IsOpen Then
                Try
                    RemoveHandler _serialPort.DataReceived, AddressOf DataReceived
                    _isRunning = False
                    _serialPort.Close()
                Catch ex As Exception
                    Return False
                End Try
            End If
            Return True
        End Function

        ' 私有方法 过时
        Private Sub ReadPressure()
            If Right(_strBuffer, 1) = Chr(NAK) Then
                _strBuffer = ""
                DequeueAndWrite()
                Exit Sub
            End If
            If _strBuffer.LastIndexOf(Chr(ACK)) = 1 And _strBuffer.LastIndexOf(Chr(ETX)) = _strBuffer.Length - 2 Then
                If Asc(_strBuffer(_strBuffer.Length - 1)) = SystemData.BCC(Mid(_strBuffer, 4, _strBuffer.Length - 4)) Then
                    CutBuffer(4) '读取去除头部 06 06 05 02
                    _info.Gp1 = CutBuffer(Len(_strBuffer) - 2)
                    Messenger.Default.Send(New Message("Middle-Info", _info), "DataReceived")
                    CutBuffer(2)
                End If
                DequeueAndWrite()
            End If
        End Sub

        Private Sub ReadGroup()
            '02 000.0 000.0 000.0 000.0 000.0 000.0 000.0 000.0 +000.0 +000.0 +000.0 -000.0 +000.0 +000.0 +000.0 +000.0 +000.0 +000.0 +000.0 +0.0000E+0 +0.0000E+0Pa      kPa    0000000.00000000000000000000000000000000000000 0000 0000
            If Right(_strBuffer, 1) = Chr(NAK) Then
                _strBuffer = ""
                DequeueAndWrite()
                Exit Sub
            End If

            If _strBuffer.LastIndexOf(Chr(ACK)) = 1 And _strBuffer.LastIndexOf(Chr(ETX)) <> -1 And
                _strBuffer.LastIndexOf(Chr(ETX)) = _strBuffer.Length - 2 Then
                If Asc(_strBuffer(_strBuffer.Length - 1)) = SystemData.BCC(Mid(_strBuffer, 4, _strBuffer.Length - 4)) Then

                    CutBuffer(4) '读取去除头部 06 06 05 02

                    _groupModel.GroupId = CutBuffer(2)

                    '环节时间
                    For i = 0 To 7
                        _groupModel.Times(i) = CutBuffer(5)
                    Next

                    '+NG -NG
                    For i = 0 To 5
                        _groupModel.Limits(i) = CutBuffer(6)
                    Next
                    '压力标准 上下限
                    For i = 6 To 10
                        _groupModel.Limits(i) = CutBuffer(6)
                    Next

                    _groupModel.WValoume = CutBuffer(10)
                    _groupModel.MValoume = CutBuffer(10)
                    _groupModel.LeakUnit = CutBuffer(8)
                    _groupModel.PressureUnit = CutBuffer(6)
                    _groupModel.LeakDigit = CutBuffer(5)
                    _groupModel.TimerDigit = CutBuffer(5)
                    _groupModel.UsbMode = CutBuffer(1)
                    _groupModel.RS232Mode = CutBuffer(1)
                    _groupModel.Cylinder = CutBuffer(1)
                    _groupModel.SV5Mode = CutBuffer(8)
                    _groupModel.Sv6Mode = CutBuffer(8)
                    _groupModel.SV7Mode = CutBuffer(8)
                    _groupModel.SV8Mode = CutBuffer(8)
                    _groupModel.MasterMode = CutBuffer(1)

                    If _mode = SystemData.Model_800 And _version <> SystemData.Version_800_113 Then
                        _groupModel.MiddleJudgment = CutBuffer(1) = "1"
                        _groupModel.LeadPDAC = CutBuffer(5)
                        _groupModel.TestPDAC = CutBuffer(5)
                        If _version = SystemData.Version_800_127 Then
                            _strBuffer = ""
                            _strOperateCommand = ReadGroupExtCmd
                            WriteToMachine(Chr(ENQ) & "?" & Chr(ACK))
                            Exit Sub
                        End If
                        Messenger.Default.Send(New Message("", _groupModel), "Group")
                    Else
                        Messenger.Default.Send(New Message("", _groupModel), "Group")
                    End If
                End If
                _strBuffer = ""
                DequeueAndWrite()
            End If
        End Sub

        Private Sub ReadGroupExt()
            If _strBuffer.Length >= 31 Then
                If Asc(_strBuffer(_strBuffer.Length - 1)) = SystemData.BCC(Mid(_strBuffer, 4, _strBuffer.Length - 4)) Then
                    CutBuffer(4)   '去除头部 06 06 05 02

                    'CutBuffer(2)   '组号 
                    '读时间
                    _groupModel.Times(8) = CutBuffer(5)

                    CutBuffer(20)
                    Messenger.Default.Send(New Message("", _groupModel), "Group")
                End If
                _strBuffer = ""
                DequeueAndWrite()
            End If
        End Sub

        Private Sub ReadWave()
            Dim startIndex = _strBuffer.IndexOf(Chr(STX))
            Dim endIndex = _strBuffer.IndexOf(Chr(ETX))

            If startIndex = -1 Then
                _strBuffer = ""
                DequeueAndWrite()
                Exit Sub
            End If

            If startIndex <> 0 Then
                _strBuffer = Mid(_strBuffer, startIndex + 1)
                startIndex = _strBuffer.IndexOf(Chr(STX))
                endIndex = _strBuffer.IndexOf(Chr(ETX))
            End If

            While (startIndex = 0 And endIndex <> -1)
                Debug.Print(Byte.Parse(SystemData.BCC(Mid(_strBuffer, 1, endIndex + 1))))
                If (Len(_strBuffer) < endIndex + 2) Then
                    Exit While
                End If
                If Asc(_strBuffer(endIndex + 1)) = SystemData.BCC(Mid(_strBuffer, 1, endIndex + 1)) Then
                    Call CutBuffer(1)         '02
                    Dim tmp As String         '环节标志
                    tmp = CutBuffer(1)
                    If tmp = "P" Then
                        Messenger.Default.Send(New Message("Process", CInt(CutBuffer(endIndex - 2))), "DataReceived")
                        CutBuffer(2)
                        startIndex = _strBuffer.IndexOf(Chr(STX))
                        endIndex = _strBuffer.IndexOf(Chr(ETX))
                        Continue While
                    ElseIf tmp = "G" Then
                        _info.Gp2 = CutBuffer(endIndex - 2)
                    ElseIf tmp = "T" Then
                        _info.Temp = CutBuffer(endIndex - 2)
                    ElseIf tmp = "D" Then
                        _info.Dp = CutBuffer(endIndex - 2)
                    Else
                        If SystemData.Machine = Model_800 Then
                            ReadWaveResult(tmp)
                        Else
                            ReadMSWaveResult(tmp)
                        End If
                        CutBuffer(2)
                        Exit While
                    End If
                    Messenger.Default.Send(New Message("Middle-Info", _info), "DataReceived")
                    CutBuffer(2)
                    startIndex = _strBuffer.IndexOf(Chr(STX))
                    endIndex = _strBuffer.IndexOf(Chr(ETX))
                Else
                    _strBuffer = ""
                    Exit While
                End If
            End While
        End Sub

        Private Sub WriteGroup()
            If Len(_strBuffer) >= 3 AndAlso Mid(_strBuffer, 1, 3) = Encoding.ASCII.GetString({ACK, ACK, ENQ}) Then
                _strBuffer = ""
                Dim cmd = g_udt800.BuildGroupCmd()
                ' 绕过队列继续写
                WriteToMachine(cmd)
                Exit Sub
            End If
            Debug.Print(_strBuffer)
            If Len(_strBuffer) >= 1 Then
                If Asc(_strBuffer(0)) = ACK Then
                    _strBuffer = ""
                    If (SystemData.Machine = Model_800 And SystemData.Version = Version_800_113) Or SystemData.Machine = Model_800MS Then
                        IsWritten = True
                        DequeueAndWrite()
                    Else
                        ' 正常写
                        _strOperateCommand = WriteGroupExtCmd
                        WriteToMachine(Chr(ENQ) & "(")
                    End If
                Else
                    _strBuffer = ""
                    IsWritten = False
                    DequeueAndWrite()
                End If
            End If
        End Sub

        Friend Function WriteGroupIdSync(groupId As UShort) As Boolean
            _strOperateCommand = SwitchGroupCmd

            Dim intTimeOut As UInt32 = 0

            Dim intTimeTick_pre As Integer = My.Computer.Clock.TickCount    '初始化定时

            Try
                ClearBuffer()
                _serialPort.Write(Chr(ENQ) & "0")
                Do
                    Thread.Sleep(100)
                    intTimeOut = My.Computer.Clock.TickCount - intTimeTick_pre
                    If Left(_strBuffer, 1) = Chr(NAK) Then
                        ClearBuffer()
                        Return False
                    End If
                Loop Until (Len(_strBuffer) >= 3) Or intTimeOut > _timeOut

                If intTimeOut >= _timeOut Then '超时
                    ClearBuffer()
                    Debug.Print("WriteGroupIdSync timeout!") '程序不中断
                    Return False
                End If

                '执行数据写入 等待响应
                If Len(_strBuffer) >= 3 AndAlso Mid(_strBuffer, 1, 3) = Encoding.ASCII.GetString({ACK, ACK, ENQ}) Then
                    ClearBuffer()
                    Dim cmd = Chr(STX) & Format(groupId, "00") & Chr(ETX)
                    Dim parity = BCC(cmd)
                    cmd &= Chr(parity)
                    ' 绕过队列继续写
                    WriteToMachine(Chr(ACK) & cmd)
                End If

                Do
                    Thread.Sleep(100)
                    intTimeOut = My.Computer.Clock.TickCount - intTimeTick_pre
                    If Left(_strBuffer, 1) = Chr(ACK) Then
                        ClearBuffer()
                        Return True
                    ElseIf Left(_strBuffer, 1) = Chr(NAK) Then
                        ClearBuffer()
                        Return False
                    End If
                Loop Until intTimeOut > _timeOut

                If intTimeOut >= _timeOut Then '超时
                    ClearBuffer()
                    Debug.Print("WriteGroupIdSync timeout!") '程序不中断
                    Return False
                End If
            Catch ex As Exception
            Finally
                _strOperateCommand = ""
            End Try
            Return False


        End Function

        Friend Function WriteSNSync(strCmd As String, productCode As String) As Boolean
            _strOperateCommand = WriteSNCmd
            Dim intTimeOut As UInt32 = 0

            Dim intTimeTick_pre As Integer = My.Computer.Clock.TickCount    '初始化定时

            Try
                '发送写入请求 等待响应
                _serialPort.Write(strCmd)
                Do
                    Thread.Sleep(100)
                    intTimeOut = My.Computer.Clock.TickCount - intTimeTick_pre
                    If Len(_strBuffer) > 1 AndAlso Asc(_strBuffer(0)) = NAK Then
                        _strBuffer = ""
                        Return False
                    End If
                Loop Until Len(_strBuffer) >= 3 Or intTimeOut > _timeOut

                If intTimeOut >= _timeOut Then '超时
                    _strBuffer = ""
                    Debug.Print("ReadPressureSync timeout!") '程序不中断
                    Return False
                End If

                '执行数据写入 等待响应
                If Len(_strBuffer) >= 3 AndAlso Mid(_strBuffer, 1, 3) = Encoding.ASCII.GetString({ACK, ACK, ENQ}) Then
                    _strBuffer = ""
                    Dim cmd = ChrW(STX) & FillInSpaces(productCode, 40) & ChrW(ETX)
                    Dim parity = BCC(cmd)
                    cmd = ChrW(ENQ) & cmd & ChrW(parity)
                    ' 绕过队列继续写
                    WriteToMachine(cmd)
                End If

                Do
                    Thread.Sleep(100)
                    intTimeOut = My.Computer.Clock.TickCount - intTimeTick_pre
                    If Left(_strBuffer, 1) = Chr(ACK) Then
                        _strBuffer = ""
                        Return True
                    ElseIf Left(_strBuffer, 1) = Chr(NAK) Then
                        _strBuffer = ""
                        Return False
                    End If
                Loop Until intTimeOut > _timeOut

                If intTimeOut >= _timeOut Then '超时
                    _strBuffer = ""
                    Debug.Print("ReadPressureSync timeout!") '程序不中断
                    Return False
                End If

            Catch ex As Exception
                Debug.Print(ex.Message)
                Return False
            Finally
                _strOperateCommand = ""
            End Try
            Return True
        End Function

        Private Sub DequeueAndWrite()
            _strOperateCommand = ""
            If _cmdQueue.Count > 0 Then
                Dim cmd As Cmd = _cmdQueue.Dequeue()
                _strOperateCommand = cmd.Type
                WriteToMachine(cmd.Cmd)
            End If
        End Sub

        Private Sub WriteGroupExt()

            Dim startIndex = _strBuffer.IndexOf(Chr(STX))
            Dim endIndex = _strBuffer.IndexOf(Chr(ETX))

            If startIndex = 0 And endIndex <> -1 Then
                CutBuffer(endIndex + 2)
            End If

            If Len(_strBuffer) >= 3 AndAlso Right(_strBuffer, 3) = Encoding.ASCII.GetString({ACK, ACK, ENQ}) Then
                Dim cmd = Chr(STX) & Format(UShort.Parse(g_udt800.GroupId), "00") &
                    FillInSpaces(Format(Double.Parse(g_udt800.Times(8)), g_udt800.TimerDigit), 5) &
                    FillInSpaces("", 20) & Chr(ETX)
                Dim parity = BCC(cmd)
                cmd &= Chr(parity)
                _strBuffer = ""
                WriteToMachine(Chr(ACK) & cmd)
                Exit Sub
            End If
            Debug.Print(String.Join(" ", Encoding.ASCII.GetBytes(_strBuffer)))
            If Len(_strBuffer) >= 1 Then
                If Asc(_strBuffer(0)) = ACK Then
                    _strBuffer = ""
                    IsWritten = True
                Else
                    _strBuffer = ""
                    IsWritten = False
                End If
                DequeueAndWrite()
            End If
        End Sub

        Private Sub ReadHistoryResult()
            Dim startIndex = _strBuffer.IndexOf(Chr(STX))
            Dim endIndex = _strBuffer.IndexOf(Chr(ETX))

            If startIndex = -1 Then
                _strBuffer = ""
                DequeueAndWrite()
                Exit Sub
            End If

            If startIndex <> 0 Then
                _strBuffer = Mid(_strBuffer, startIndex + 1)
                startIndex = _strBuffer.IndexOf(Chr(STX))
                endIndex = _strBuffer.IndexOf(Chr(ETX))
            End If

            While (startIndex = 0 And endIndex <> -1)
                Debug.Print(Byte.Parse(SystemData.BCC(Mid(_strBuffer, 1, endIndex + 1))))
                If (Len(_strBuffer) < endIndex + 2) Then
                    Exit While
                End If
                If Asc(_strBuffer(endIndex + 1)) = SystemData.BCC(Mid(_strBuffer, 1, endIndex + 1)) Then
                    Call CutBuffer(1)         '02
                    Dim tmp As String         '环节标志
                    tmp = CutBuffer(1)
                    If SystemData.Machine = Model_800 Then
                        ReadWaveResult(tmp)
                    Else
                        ReadMSWaveResult(tmp)
                    End If
                    CutBuffer(2)
                    Messenger.Default.Send(New Message("Middle-Info", _info), "DataReceived")
                    startIndex = _strBuffer.IndexOf(Chr(STX))
                    endIndex = _strBuffer.IndexOf(Chr(ETX))
                Else
                    _strBuffer = ""
                    Exit While
                End If
            End While
        End Sub

        Private Sub ReadWaveResult(ByVal no As String)
            _resultModel.No = no & CutBuffer(3)
            _resultModel.Group = CutBuffer(2)
            _resultModel.DateTime = Convert.ToDateTime(CutBuffer(19))
            For i = 0 To 6
                _resultModel.Timers(i) = CutBuffer(5)
            Next
            _resultModel.Sdet = CutBuffer(6)
            _resultModel.Unit = CutBuffer(8)
            _resultModel.Judgment = CutBuffer(4)
            Messenger.Default.Send(New Message("Result", _resultModel), "DataReceived")
        End Sub

        Private Sub ReadMSWaveResult(ByVal no As String)
            _resultModel.No = no & CutBuffer(3)
            _resultModel.Group = CutBuffer(2)
            _resultModel.DateTime = Convert.ToDateTime(CutBuffer(19))
            For i = 0 To 6
                _resultModel.Timers(i) = CutBuffer(5)
            Next
            _resultModel.Sdet = CutBuffer(6)
            _resultModel.Ldet = CutBuffer(6)
            _resultModel.Unit = CutBuffer(8)
            _resultModel.Judgment = CutBuffer(4)
            Messenger.Default.Send(New Message("Result", _resultModel), "DataReceived")
        End Sub

        Private Sub DataReceived(ByVal s As Object, ByVal e As SerialDataReceivedEventArgs)
            Dim serialPort = TryCast(s, SerialPort)
            If serialPort Is Nothing Then
                Exit Sub
            End If

            Dim intBytesToRead = serialPort.BytesToRead

            Dim bytes(intBytesToRead - 1) As Byte

            serialPort.Read(bytes, 0, intBytesToRead)

            _strBuffer &= Encoding.ASCII.GetString(bytes)

            '_strBuffer &= Chr(serialPort.ReadByte())

            'Debug.Print(String.Join(" ", Encoding.ASCII.GetBytes(_strBuffer)))

            Select Case _strOperateCommand
                Case SystemData.ReadGroupCmd, SystemData.ReadGroupExtCmd, SystemData.OperateCmd,
                     SystemData.WriteGroupCmd, SystemData.WriteGroupExtCmd, SystemData.ReadPressureCmd,
                     SystemData.SwitchGroupCmd
                    Debug.Print("Sync Opearate")
                Case SystemData.ReadResultCmd, SystemData.ReadWaveCmd
                    ReadWave()
                Case Else
                    ReadWave()
            End Select




            'If _strOperateCommand = SystemData.ReadGroupCmd Then
            '    ReadGroup()
            'ElseIf _strOperateCommand = SystemData.ReadGroupExtCmd Then
            '    ReadGroupExt()
            'ElseIf _strOperateCommand = SystemData.OperateCmd Then
            '    ReadOperateResult()
            'ElseIf _strOperateCommand = SystemData.WriteGroupCmd Then
            '    WriteGroup()
            'ElseIf _strOperateCommand = SystemData.WriteGroupExtCmd Then
            '    WriteGroupExt()
            'ElseIf _strOperateCommand = SystemData.ReadPressureCmd Then
            '    ReadPressure()
            'ElseIf _strOperateCommand = SystemData.ReadResultCmd Then
            '    ReadHistoryResult()
            'ElseIf _strOperateCommand = SystemData.ReadWaveCmd Then
            '    ReadWave()
            'Else
            '    ReadWave()
            '    _strBuffer = ""
            'End If

        End Sub

        Private Sub ReadOperateResult()
            If Len(_strBuffer) > 4 Then
                _strBuffer = ""
            ElseIf Len(_strBuffer) = 4 Then
                _strBuffer = ""
            ElseIf Len(_strBuffer) > 2 Then
                CutBuffer(2)
            End If
            DequeueAndWrite()
        End Sub




        Public Sub Write(ByVal strCommand As String, ByVal strType As String)
            If _cmdQueue IsNot Nothing Then
                _cmdQueue.Enqueue(New Cmd() With {.Type = strType, .Cmd = strCommand})
                If _strOperateCommand = "" Then
                    Dim cmd As Cmd = _cmdQueue.Dequeue
                    _strOperateCommand = cmd.Type
                    WriteToMachine(cmd.Cmd)
                End If
            End If
        End Sub

        Private Sub WriteToMachine(ByVal command As String)
            If Not _serialPort.IsOpen Then
                MsgBox("串口未打开")
                Exit Sub
            End If
            _serialPort.Write(command)
        End Sub


        Public Function ReadPressureSync(strCmd As String) As Boolean
            Dim cmd As New Cmd() With {
                .Type = ReadPressureCmd,
                .Cmd = strCmd}
            Return ReadSyncBase(cmd,
                                Sub(intStart As Integer, intEnd As Integer)
                                    CutBuffer(intStart + 2)
                                    _info.Gp1 = CutBuffer(intEnd - intStart - 1)
                                    Messenger.Default.Send(New Message("Pressure", _info), "DataReceived")
                                    CutBuffer(2)
                                End Sub)
        End Function

        Public Function ReadGroupSync(strCmd As String) As Boolean
            Dim cmd As New Cmd() With {
                .Type = ReadGroupCmd,
                .Cmd = strCmd}

            Return ReadSyncBase(cmd,
                         Sub(intStart As Integer, intEnd As Integer)
                             CutBuffer(intStart + 1) '读取去除头部 06 06 05 02

                             _groupModel.GroupId = CutBuffer(2)

                             '环节时间
                             For i = 0 To 7
                                 _groupModel.Times(i) = CutBuffer(5)
                             Next

                             '+NG -NG
                             For i = 0 To 5
                                 _groupModel.Limits(i) = CutBuffer(6)
                             Next
                             '压力标准 上下限
                             For i = 6 To 10
                                 _groupModel.Limits(i) = CutBuffer(6)
                             Next

                             _groupModel.WValoume = CutBuffer(10)
                             _groupModel.MValoume = CutBuffer(10)
                             _groupModel.LeakUnit = CutBuffer(8)
                             _groupModel.PressureUnit = CutBuffer(6)
                             _groupModel.LeakDigit = CutBuffer(5)
                             _groupModel.TimerDigit = CutBuffer(5)
                             _groupModel.UsbMode = CutBuffer(1)
                             _groupModel.RS232Mode = CutBuffer(1)
                             _groupModel.Cylinder = CutBuffer(1)
                             _groupModel.SV5Mode = CutBuffer(8)
                             _groupModel.Sv6Mode = CutBuffer(8)
                             _groupModel.SV7Mode = CutBuffer(8)
                             _groupModel.SV8Mode = CutBuffer(8)
                             _groupModel.MasterMode = CutBuffer(1)

                             If _mode = SystemData.Model_800 And _version <> SystemData.Version_800_113 Then
                                 _groupModel.MiddleJudgment = CutBuffer(1) = "1"
                                 _groupModel.LeadPDAC = CutBuffer(5)
                                 _groupModel.TestPDAC = CutBuffer(5)
                                 If _version = SystemData.Version_800_127 Then
                                     _strBuffer = ""
                                     ReadGroupExtSync(Chr(ENQ) & "?" & Chr(ACK))
                                     Exit Sub
                                 End If
                                 CutBuffer(2)
                                 Messenger.Default.Send(New Message("", _groupModel), "Group")
                             Else
                                 CutBuffer(2)
                                 Messenger.Default.Send(New Message("", _groupModel), "Group")
                             End If
                         End Sub)
        End Function

        Public Function ReadGroupExtSync(strCmd As String) As Boolean
            Dim cmd As New Cmd() With {
                .Type = ReadGroupExtCmd,
                .Cmd = strCmd}

            Return ReadSyncBase(cmd,
                         Sub(intStart As Integer, intEnd As Integer)
                             CutBuffer(intStart + 1)   '去除头部 06 06 05 02

                             'CutBuffer(2)   '组号 
                             '读时间
                             _groupModel.Times(8) = CutBuffer(5)

                             CutBuffer(22)
                             Messenger.Default.Send(New Message("", _groupModel), "Group")
                         End Sub)

        End Function


        Public Function WriteGroupSync(strCmd As String) As Boolean
            _strOperateCommand = WriteGroupCmd
            Dim intTimeOut As UInt32 = 0

            Dim intTimeTick_pre As Integer = My.Computer.Clock.TickCount    '初始化定时

            Try
                ClearBuffer()
                '发送写入请求 等待响应
                _serialPort.Write(strCmd)
                Do
                    Thread.Sleep(100)
                    intTimeOut = My.Computer.Clock.TickCount - intTimeTick_pre
                    If Len(_strBuffer) > 1 AndAlso Asc(_strBuffer(0)) = NAK Then
                        ClearBuffer()
                        Return False
                    End If
                Loop Until Len(_strBuffer) >= 3 Or intTimeOut > _timeOut

                If intTimeOut >= _timeOut Then '超时
                    ClearBuffer()
                    Debug.Print("WriteGroupSync timeout!") '程序不中断
                    Return False
                End If

                '执行数据写入 等待响应
                If Len(_strBuffer) >= 3 AndAlso Mid(_strBuffer, 1, 3) = Encoding.ASCII.GetString({ACK, ACK, ENQ}) Then
                    _strBuffer = ""
                    Dim cmd = g_udt800.BuildGroupCmd()
                    ' 绕过队列继续写
                    WriteToMachine(cmd)
                End If

                Do
                    Thread.Sleep(100)
                    intTimeOut = My.Computer.Clock.TickCount - intTimeTick_pre
                    If Left(_strBuffer, 1) = Chr(ACK) Then
                        _strBuffer = ""
                        If (SystemData.Machine = Model_800 And SystemData.Version = Version_800_113) Or
                            SystemData.Machine = Model_800MS Then
                            _strOperateCommand = ""
                            Return True
                        Else
                            ' 正常写
                            Return WriteGroupExtSync(Chr(ENQ) & "(")
                        End If
                    ElseIf Left(_strBuffer, 1) = Chr(NAK) Then
                        _strBuffer = ""
                        Return False
                    End If
                Loop Until intTimeOut > _timeOut * 3

                If intTimeOut >= _timeOut * 3 Then '超时
                    _strBuffer = ""
                    Debug.Print("WriteGroupSync timeout!") '程序不中断
                    Return False
                End If

            Catch ex As Exception
                Debug.Print(ex.Message)
                Return False
            Finally
                _strOperateCommand = ""
            End Try
            Return True
        End Function

        Public Function WriteGroupExtSync(strCmd As String) As Boolean
            _strOperateCommand = WriteGroupCmd
            Dim intTimeOut As UInt32 = 0

            Dim startIndex = _strBuffer.IndexOf(Chr(STX))
            Dim endIndex = _strBuffer.IndexOf(Chr(ETX))

            If startIndex = 0 And endIndex <> -1 Then
                CutBuffer(endIndex + 2)
            End If

            Dim intTimeTick_pre As Integer = My.Computer.Clock.TickCount    '初始化定时

            Try
                ClearBuffer()
                '发送写入请求 等待响应
                _serialPort.Write(strCmd)
                Do
                    Thread.Sleep(100)
                    intTimeOut = My.Computer.Clock.TickCount - intTimeTick_pre
                    If Left(_strBuffer, 1) = Chr(NAK) Then
                        ClearBuffer()
                        Return False
                    End If
                Loop Until Len(_strBuffer) >= 3 Or intTimeOut > _timeOut

                If intTimeOut >= _timeOut Then '超时
                    ClearBuffer()
                    Debug.Print("WriteGroupExtSync timeout!") '程序不中断
                    Return False
                End If

                '执行数据写入 等待响应
                If Len(_strBuffer) >= 3 AndAlso Mid(_strBuffer, 1, 3) = Encoding.ASCII.GetString({ACK, ACK, ENQ}) Then
                    ClearBuffer()
                    Dim cmd = Chr(STX) & Format(UShort.Parse(g_udt800.GroupId), "00") &
                    FillInSpaces(Format(Double.Parse(g_udt800.Times(8)), g_udt800.TimerDigit), 5) &
                    FillInSpaces("", 20) & Chr(ETX)
                    Dim parity = BCC(cmd)
                    cmd &= Chr(parity)
                    ClearBuffer()
                    WriteToMachine(Chr(ACK) & cmd)
                End If

                startIndex = _strBuffer.IndexOf(Chr(STX))
                endIndex = _strBuffer.IndexOf(Chr(ETX))

                If startIndex = 0 And endIndex <> -1 Then
                    CutBuffer(endIndex + 2)
                End If

                Do
                    Thread.Sleep(100)
                    intTimeOut = My.Computer.Clock.TickCount - intTimeTick_pre
                    If Left(_strBuffer, 1) = Chr(ACK) Then
                        ClearBuffer()
                        Return True
                    ElseIf Left(_strBuffer, 1) = Chr(NAK) Then
                        ClearBuffer()
                        Return False
                    End If
                Loop Until intTimeOut > _timeOut

                If intTimeOut >= _timeOut Then '超时
                    ClearBuffer()
                    Debug.Print("WriteGroupExtSync timeout!") '程序不中断
                    Return False
                End If

            Catch ex As Exception
                Return False
            Finally
                _strOperateCommand = ""
            End Try
            Return True
        End Function

        Public Function WriteOperateSync(strCmd As String) As Boolean
            _strOperateCommand = WriteGroupCmd

            Dim intTimeOut As UInt32 = 0

            Dim intTimeTick_pre As Integer = My.Computer.Clock.TickCount    '初始化定时

            Try
                ClearBuffer()
                _serialPort.Write(strCmd)
                Do
                    Thread.Sleep(100)
                    intTimeOut = My.Computer.Clock.TickCount - intTimeTick_pre
                    If Left(_strBuffer, 1) = Chr(NAK) Then
                        ClearBuffer()
                        Return False
                    End If
                Loop Until (Len(_strBuffer) >= 2) Or intTimeOut > _timeOut

                If intTimeOut >= _timeOut Then '超时
                    ClearBuffer()
                    Debug.Print("WriteOperateSync timeout!") '程序不中断
                    Return False
                End If

                If Right(_strBuffer, 2) = Encoding.ASCII.GetString({ACK, ACK}) Then
                    ClearBuffer()
                    Return True
                End If
            Catch ex As Exception
            Finally
                _strOperateCommand = ""
            End Try
            Return False
        End Function

        Public Function WriteResetSync(strCmd As String) As Boolean
            _strOperateCommand = OperateCmd

            Dim intTimeOut As UInt32 = 0

            Dim intTimeTick_pre As Integer = My.Computer.Clock.TickCount    '初始化定时

            Try
                ClearBuffer()
                _serialPort.Write(strCmd)
                Do
                    Thread.Sleep(100)
                    intTimeOut = My.Computer.Clock.TickCount - intTimeTick_pre
                    If Left(_strBuffer, 1) = Chr(NAK) Then
                        ClearBuffer()
                        Return False
                    End If
                Loop Until (Len(_strBuffer) >= 2) Or intTimeOut > _timeOut

                If intTimeOut >= _timeOut Then '超时
                    ClearBuffer()
                    Debug.Print("WriteResetSync timeout!") '程序不中断
                    Return False
                End If

                If _strBuffer(_strBuffer.Length - 2) = Encoding.ASCII.GetString({ACK}) Then
                    ClearBuffer()
                    Return True
                End If
            Catch ex As Exception
            Finally
                _strOperateCommand = ""
            End Try
            Return False
        End Function

        Private Function ReadSyncBase(cmd As Cmd, func As Action(Of Integer, Integer)) As Boolean
            _strOperateCommand = cmd.Type

            Dim intTimeOut As UInt32 = 0

            Dim intTimeTick_pre As Integer = My.Computer.Clock.TickCount    '初始化定时

            Dim intStart As Int16 = 0
            Dim intEnd As Int16 = 0

            Try
                ClearBuffer()
                _serialPort.Write(cmd.Cmd)
                Do
                    Thread.Sleep(10)
                    intTimeOut = My.Computer.Clock.TickCount - intTimeTick_pre
                    If Left(_strBuffer, 1) = Chr(NAK) Then
                        ClearBuffer()
                        Return False
                    End If
                    intStart = _strBuffer.IndexOf(Chr(STX))
                    intEnd = _strBuffer.IndexOf(Chr(ETX))
                Loop Until (intStart > 0 And intEnd > 0 AndAlso Len(_strBuffer) >= intEnd + 2) Or intTimeOut > _timeOut

                If intTimeOut >= _timeOut Then '超时
                    ClearBuffer()
                    Debug.Print("ReadPressureSync timeout!") '程序不中断
                    Return False
                End If
                If Asc(_strBuffer(intEnd + 1)) = SystemData.BCC(Mid(_strBuffer, intStart + 1, intEnd - intStart + 1)) Then
                    func(intStart, intEnd)
                    _strOperateCommand = ""
                    Return True
                Else
                    CutBuffer(intEnd + 2)
                    Return False
                End If
            Catch ex As Exception
                MsgBox(cmd.Type & " failed " & ex.Message)
                Debug.Print(ex.StackTrace.ToString)
                Return False
            Finally
                _strOperateCommand = ""
            End Try
        End Function

    End Class

End Namespace